#include "helper/sqlite/stream/Scalar.h"

#include "helper/sqlite/QueryResult.h"
#include "helper/sqlite/Value.h"


namespace helper {
namespace sqlite {
namespace stream {

template<typename T>
inline T __value(const std::optional<Value> & value){
  return T();
}
template<>
inline std::string __value<std::string>(const std::optional<Value> & value){
  return value->string();
}
template<>
inline int64_t __value<int64_t>(const std::optional<Value> & value){
  return value->integer();
}
template<>
inline double __value<double>(const std::optional<Value> & value){
  return value->real();
}

template<typename T>
std::optional<T> value(const QueryResult & result, std::error_code & ec){
  if(auto && value = result.values(0); value){
    auto && v = __value<T>(value);
    return std::optional<T>(std::move(v));
  }
  ec = std::make_error_code(std::errc::invalid_argument);
  return std::nullopt;
}

Scalar::Scalar(QueryResult & r)
  :_result(r)
{
}
Scalar::~Scalar(){}

std::optional<std::string> Scalar::text(std::error_code & ec) {
  return value<std::string>(_result, ec);
}
std::optional<double> Scalar::real(std::error_code & ec) {
  return value<double>(_result, ec);
}
std::optional<int64_t> Scalar::integer(std::error_code & ec) {
  return value<int64_t>(_result, ec);
}
std::optional<std::string> Scalar::binary(std::error_code & ec) {
  return value<std::string>(_result, ec);
}

}//namespace stream
}//namespace sqlite
}//namespace helper
